home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
demo
/
rotplnnr.lha
/
RoutePlanner.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-22
|
68KB
|
2,317 lines
/* RoutePlanner.c -- A fancy-ass front-end for RoadRoute */
/* (C) 1994 Chris Lawrence */
#include "RoutePlanner.h"
#include "RoutePlanner_rev.h"
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/muimaster.h>
#include <proto/icon.h>
#include <proto/utility.h>
#include <proto/intuition.h>
#include <proto/asl.h>
#include <libraries/mui.h>
#include <libraries/gadtools.h>
#include <dos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <reg.h>
extern struct Library *MUIMasterBase;
extern struct Library *IconBase;
extern struct Library *UtilityBase;
extern struct IntuitionBase *IntuitionBase;
extern struct Library *AslBase;
void _STD_32767_killapp(void);
void main(int argc, char **argv);
ULONG ChooseCity(struct CityData *cd, ULONG Cities, ULONG CurrentCity,
char *tbar);
BOOL OpenDatabase(char *filename, struct CityData **cd,
struct RouteData **rd);
BOOL GetFile(char *filename, BOOL saverequest, char *tbar);
void AddListEntries(APTR list, struct CityData *cd, ULONG CityCount);
void Navigate(struct CityData *cd, struct CityData *Start,
struct CityData *Finish);
BOOL NavCoord(struct CityData *cd, struct RouteData *rd,
ULONG fromID, ULONG toID, ULONG *viaID, ULONG viacount);
UWORD ConvertDist(UWORD srcDist, UWORD srcUnits, UWORD destUnits);
UWORD ConvertToTime(UWORD Code, UWORD SVal, UWORD Dist, UWORD RteUnits,
UWORD SysUnits);
UWORD ConvertEfficiency(UWORD srcEff, UWORD SrcUnits, UWORD destUnits);
void SPrintf(char *outstr, char *fmt, ...);
#define ROUTETYPES 18
// Special list constructors and destructors
APTR __saveds __asm constructor(register __a2 APTR pool,
register __a1 struct CityData *entry);
APTR __saveds __asm constructor(register __a2 APTR pool,
register __a1 struct CityData *entry)
{
struct CityName *cn;
if(cn=malloc(sizeof(struct CityName)))
{
cn->cn_CityID=entry->CityID;
SPrintf(cn->cn_Name,"%s, %s",entry->CityName,entry->StateName);
}
return cn;
}
VOID __saveds __asm destructor(register __a2 APTR pool,
register __a1 struct CityName *entry);
VOID __saveds __asm destructor(register __a2 APTR pool,
register __a1 struct CityName *entry)
{
free(entry);
}
LONG __saveds __asm display(register __a2 char **array,
register __a1 struct CityName *cn);
LONG __saveds __asm display(register __a2 char **array,
register __a1 struct CityName *cn)
{
*array=cn->cn_Name;
return 0;
}
LONG __saveds __asm compare(register __a1 struct CityName *cn1,
register __a2 struct CityName *cn2);
LONG __saveds __asm compare(register __a1 struct CityName *cn1,
register __a2 struct CityName *cn2)
{
return(Stricmp(cn1->cn_Name,cn2->cn_Name));
}
struct Hook comphook={{NULL,NULL},&compare,NULL,NULL};
struct Hook consthook={{NULL,NULL},(HOOKFUNC)&constructor,NULL,NULL};
struct Hook desthook={{NULL,NULL},(HOOKFUNC)&destructor,NULL,NULL};
struct Hook disphook={{NULL,NULL},&display,NULL,NULL};
// General Defines
#define MAXTRAIL 1000 // Visit up to 1000 cities on a route
#define COPYRIGHT VERS" ("DATE") -- Copyright 1994 Chris Lawrence"
#define MAXVIA 10
static struct CityTrail Trail[MAXTRAIL][2];
unsigned short TrailPoint[2];
// Global variables
APTR app=NULL, mainwindow=NULL, POP_DBase=NULL;
APTR prefswindow,CY_Measure,ST_Speed[ROUTETYPES],ST_MPG[ROUTETYPES];
APTR LB_Speed[ROUTETYPES], LB_MPG[ROUTETYPES];
APTR ST_DBase, BT_DBase, ST_DefaultMPG, LB_DefaultMPG;
APTR LI_ViaList, LV_ViaList;
APTR TX_FromCity, TX_ToCity, BT_FromCity, BT_ToCity;
APTR BT_DoRoute, BT_Quit, BT_SavePrefs, BT_UsePrefs, BT_CancelPrefs;
APTR GP_Speed[2], GP_MPG[2], REG_Prefs;
APTR BT_AddCity, BT_ChangeCity, BT_RemoveCity, BT_MoveUp, BT_MoveDown;
ULONG MeasureUnits, Speed[ROUTETYPES], MPG[ROUTETYPES], DefaultMPG;
ULONG DisplayType, debugoutput;
#define DIS_ALL (0L)
#define DIS_ROUTECHANGE (1L)
#define DIS_STATECHANGE (2L)
struct DiskObject *disko=NULL;
APTR memptr=NULL;
ULONG cdcount, rdcount;
struct DataBaseInfo *dbi=NULL;
APTR DLabel(const char *string);
APTR DLabel(const char *string)
{
APTR tmp;
tmp=TextObject,
StringFrame,
MUIA_FramePhantomHoriz, TRUE,
MUIA_Text_SetMin, FALSE,
MUIA_Text_SetMax, FALSE,
MUIA_FixWidthTxt, "km/h",
MUIA_Text_PreParse, MUIX_L,
MUIA_Text_Contents, string,
MUIA_InputMode, MUIV_InputMode_None,
End;
return tmp;
}
void _STD_32767_killapp(void)
{
// SAS/C Autotermination function
// This removes the application using MUI_DisposeObject. It is called
// when the program exits. Normal exits would also save the application
// object.
if(memptr) free(memptr);
if(disko) FreeDiskObject(disko);
if(app) MUI_DisposeObject(app);
}
// Defines for menus and gadgets
#define ABOUT (1L)
#define QUIT (MUIV_Application_ReturnID_Quit)
#define OPEN (2L)
#define PREFS (3L)
#define HIDE (4L)
#define USEPREFS (5L) // Store to ENV:
#define SAVEPREFS (6L) // Store to ENV: and ENVARC:
#define CANCELPREFS (7L) // Same as RestorePrefs
#define OPENPREFS (8L)
#define SAVEPREFSAS (9L)
#define RESTOREPREFS (10L) // Restore from ENV:
#define RESETPREFS (11L) // Reset to defaults
#define LASTSAVEDPREFS (12L) // Restore from ENVARC:
#define FROMCITY (13L)
#define TOCITY (14L)
#define DOROUTE (15L)
#define ADDCITY (17L)
#define CHANGECITY (18L)
#define REMOVECITY (19L)
#define MOVEUP (20L)
#define MOVEDOWN (21L)
#define VIALIST (22L)
#define MEASURECHANGE (23L)
#define INFO (24L)
// Main window menu set
struct NewMenu mainmenu[]={
NM_TITLE,"Project",NULL,0L,0L,NULL,
NM_ITEM,"Open Map...","O",0L,0L,(APTR)OPEN,
NM_ITEM,NM_BARLABEL,NULL,0L,0L,NULL,
NM_ITEM,"About...","?",0L,0L,(APTR)ABOUT,
NM_ITEM,"Information...","I",0L,0L,(APTR)INFO,
NM_ITEM,NM_BARLABEL,NULL,0L,0L,NULL,
NM_ITEM,"Hide","H",0L,0L,(APTR)HIDE,
NM_ITEM,"Quit","Q",0L,0L,(APTR)QUIT,
NM_TITLE,"Settings",NULL,0L,0L,NULL,
NM_ITEM,"Preferences...","P",0L,0L,(APTR)PREFS,
NM_END,NULL,NULL,0L,0L,NULL
};
// Prefs window menu set
struct NewMenu prefsmenu[]={
NM_TITLE,"Prefs",NULL,0L,0L,NULL,
NM_ITEM,"Open...","O",0L,0L,(APTR)OPENPREFS,
NM_ITEM,"Save As...","A",0L,0L,(APTR)SAVEPREFSAS,
NM_ITEM,NM_BARLABEL,NULL,0L,0L,NULL,
NM_ITEM,"Close Prefs","C",0L,0L,(APTR)CANCELPREFS,
NM_ITEM,"Quit RoutePlanner","Q",0L,0L,(APTR)QUIT,
NM_TITLE,"Edit",NULL,0L,0L,NULL,
NM_ITEM,"Reset to Defaults","D",0L,0L,(APTR)RESETPREFS,
NM_ITEM,"Last Saved","L",0L,0L,(APTR)LASTSAVEDPREFS,
NM_ITEM,"Restore","R",0L,0L,(APTR)RESTOREPREFS,
NM_TITLE,"Settings",NULL,NM_MENUDISABLED,0L,NULL,
NM_ITEM,"Create Icons?","I",CHECKIT|MENUTOGGLE,0L,NULL,
NM_END,NULL,NULL,0L,0L,NULL
};
__inline APTR MakeMenustrip(struct NewMenu *nm);
__inline APTR MakeMenustrip(struct NewMenu *nm)
{
return MUI_MakeObject(MUIO_MenustripNM,nm,0);
}
APTR KeyPopButton(ULONG img, char key);
APTR KeyPopButton(ULONG img, char key)
{
return (ImageObject,
ImageButtonFrame,
MUIA_ControlChar, key,
MUIA_Image_Spec, img,
MUIA_Image_FontMatch, TRUE,
MUIA_InputMode, MUIV_InputMode_RelVerify,
MUIA_Background, MUII_ButtonBack,
End);
}
#define setinteger(obj,num) set(obj,MUIA_String_Integer,num)
#undef KeyButton
APTR KeyButton(char *label, char key);
APTR KeyButton(char *label, char key)
{
return (TextObject,
ButtonFrame,
MUIA_Text_Contents, label,
MUIA_Text_PreParse, MUIX_C,
MUIA_Text_HiChar, key,
MUIA_ControlChar, key,
MUIA_InputMode, MUIV_InputMode_RelVerify,
MUIA_Background, MUII_ButtonBack,
MUIA_Weight, 25,
End);
}
APTR SimpleText(char *text);
APTR SimpleText(char *text)
{
return(TextObject,
TextFrame,
MUIA_Text_Contents, text,
MUIA_InputMode, MUIV_InputMode_None,
MUIA_Background, MUII_TextBack,
End);
}
static const char *distnames[]={"kilometer","mile",NULL};
static const char *distabbrevs[]={"km","mi",NULL};
static const char *speedabbrevs[]={"km/h","mph",NULL};
static const char *mpgabbrevs[]={"km/l","mpg",NULL};
static const char *fuelunits[]={"liter","gallon",NULL};
static const char *titles[]={"Average Speed", "Fuel Efficiency",
"Miscellaneous Prefs", NULL};
static const char *measurelabels[]={"Metric", "English", NULL};
static const char *displaylabels[]={
"All cities",
"Turns only",
"State lines and turns",
NULL
};
static const char *hiwaylabels[]={
"Rural Interstate",
"Suburban Interstate",
"Urban Interstate",
"Rural Highway (4 Lane)",
"Rural Highway (2 Lane)",
"Suburban Highway",
"Suburban Road",
"Urban Road",
"Rural Interstate (55)",
"Metro Interstate",
"Autoroute (Canada)",
"Main Highway (Canada)",
"Rural Motorway (UK)",
"Suburban Motorway (UK)",
"Urban Motorway (UK)",
"Primary 4 Lane (UK)",
"Primary 2 Lane (UK)",
"Other Route (UK)",
NULL
};
void ButtonBehave(APTR button, LONG notifyval);
void ButtonBehave(APTR button, LONG notifyval)
{
DoMethod((ULONG *)button,MUIM_Notify,MUIA_Pressed,FALSE,app,2,
MUIM_Application_ReturnID, notifyval);
}
void StringBehave(APTR string, LONG notifyval);
void StringBehave(APTR string, LONG notifyval)
{
DoMethod((ULONG *)string,MUIM_Notify,MUIA_String_Acknowledge,
MUIV_EveryTime, app, 2, MUIM_Application_ReturnID, notifyval);
}
void CycleBehave(APTR cycle, LONG notifyval);
void CycleBehave(APTR cycle, LONG notifyval)
{
DoMethod((ULONG *)cycle,MUIM_Notify,MUIA_Cycle_Active,
MUIV_EveryTime, app, 2, MUIM_Application_ReturnID, notifyval);
}
void DoStuff(ULONG i, ULONG gnum);
void DoStuff(ULONG i, ULONG gnum)
{
APTR tempobj;
tempobj=Label2(hiwaylabels[i]);
ST_Speed[i]=StringObject,
StringFrame,
MUIA_String_MaxLen, 5,
MUIA_String_Integer, Speed[i],
MUIA_String_Accept, "0123456789",
MUIA_String_Format, MUIV_String_Format_Right,
MUIA_ExportID, (i+100),
End;
LB_Speed[i]=DLabel(speedabbrevs[MeasureUnits]);
DoMethod((ULONG *)GP_Speed[gnum],OM_ADDMEMBER,tempobj);
DoMethod((ULONG *)GP_Speed[gnum],OM_ADDMEMBER,ST_Speed[i]);
DoMethod((ULONG *)GP_Speed[gnum],OM_ADDMEMBER,LB_Speed[i]);
tempobj=Label2(hiwaylabels[i]);
ST_MPG[i]=StringObject,
StringFrame,
MUIA_String_MaxLen, 5,
MUIA_String_Integer, MPG[i],
MUIA_String_Accept, "0123456789",
MUIA_String_Format, MUIV_String_Format_Right,
MUIA_ExportID, (i+200),
End;
LB_MPG[i]=DLabel(mpgabbrevs[MeasureUnits]);
DoMethod((ULONG *)GP_MPG[gnum],OM_ADDMEMBER,tempobj);
DoMethod((ULONG *)GP_MPG[gnum],OM_ADDMEMBER,ST_MPG[i]);
DoMethod((ULONG *)GP_MPG[gnum],OM_ADDMEMBER,LB_MPG[i]);
}
void main(int argc, char **argv)
{
// This is the "main loop" function. It handles the application main
// window, calls the ChooseCity and ChangePrefs routines, and calls
// the router and I/O routine, Navigate.
APTR CY_Display, CB_Debug;
ULONG from=-1, to=-1, via[MAXVIA], viacount=0; // Array of city identifiers
// Miscellaneous prefs
ULONG DefMeasureUnits=UNITS_ENGLISH, OldUnits;
ULONG DefSpeed[ROUTETYPES]={65,55,40,52,50,40,30,25,60,30,62,56,70,60,
50,65,50,40};
ULONG DefMPG[ROUTETYPES]={22,21,19,20,19,17,16,15,21,17,22,21,22,21,20,
18,17,16};
ULONG DefDefaultMPG=19;
UWORD DefDisplayType=DIS_ROUTECHANGE;
BOOL DefDebugOutput=FALSE, fullinfo=FALSE;
struct MUIP_Window_SetCycleChain *scc;
static struct CityData *cd;
static struct RouteData *rd;
static char *DefDBase="Basic-USA.route",DBase[256],*tempstr;
static char filename[256]="", CurrentDBase[256];
BOOL going=TRUE, ok;
ULONG i, sigs, temp;
for(i=0;i<MAXVIA;i++) via[i]=-1;
strcpy(DBase,DefDBase);
MeasureUnits=DefMeasureUnits;
memcpy(Speed,DefSpeed,sizeof(Speed));
memcpy(MPG,DefMPG,sizeof(Speed));
DefaultMPG=DefDefaultMPG;
DisplayType=DefDisplayType;
debugoutput=DefDebugOutput;
if(!argc)
{
argc=_WBArgc;
argv=_WBArgv;
}
app=ApplicationObject,
MUIA_Application_Title, "RoutePlanner",
MUIA_Application_Version, "$VER: "VERS" ("DATE")",
MUIA_Application_Copyright, "Copyright (C) 1994 Chris Lawrence",
MUIA_Application_Author, "Chris Lawrence",
MUIA_Application_Description,"Highway Trip Planner",
MUIA_Application_Base, "ROUTEPLANNER",
MUIA_Application_SingleTask, FALSE,
MUIA_Application_DiskObject,
disko=GetDiskObjectNew("PROGDIR:RoutePlanner"),
MUIA_Application_HelpFile, "PROGDIR:RoutePlanner.guide",
// MUIA_Application_Commands, COMMANDS,
SubWindow,
mainwindow=WindowObject,
MUIA_Window_Title, VERS,
MUIA_Window_ID, 'RPLN',
MUIA_Window_Menustrip, MakeMenustrip(mainmenu),
MUIA_Window_ScreenTitle, COPYRIGHT,
MUIA_HelpNode, "MainWindow",
WindowContents,
VGroup,
Child,VGroup,
Child,ColGroup(2),
Child,BT_FromCity=KeyButton("From...",'f'),
Child,TX_FromCity=SimpleText(""),
Child,BT_ToCity=KeyButton("To...",'t'),
Child,TX_ToCity=SimpleText(""),
End,
Child,VGroup,
MUIA_HelpNode, "ViaCities",
GroupFrameT("Via"),
Child,LV_ViaList=ListviewObject,
MUIA_Listview_List, LI_ViaList=ListObject,
InputListFrame,
MUIA_List_CompareHook, &comphook,
MUIA_List_ConstructHook, &consthook,
MUIA_List_DestructHook, &desthook,
MUIA_List_DisplayHook, &disphook,
End,
MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_None,
End,
Child,HGroup,
Child, HGroup,
MUIA_Group_SameSize, TRUE,
Child,BT_AddCity=KeyButton("Add...",'a'),
Child,BT_ChangeCity=KeyButton("Change...",'c'),
Child,BT_RemoveCity=KeyButton("Remove",'r'),
End,
Child, HGroup,
MUIA_Weight, 0,
Child,BT_MoveUp=KeyPopButton(MUII_ArrowUp,'u'),
Child,BT_MoveDown=KeyPopButton(MUII_ArrowDown,'d'),
End,
End,
End,
End,
Child,HGroup,
Child,BT_DoRoute=KeyButton("Plan Route...",'p'),
Child,BT_Quit=KeyButton("Quit RoutePlanner",'q'),
MUIA_Group_SameSize, TRUE,
End,
End,
End,
SubWindow,
prefswindow=WindowObject,
MUIA_Window_Title, "RoutePlanner Prefs",
MUIA_Window_ID, 'RPPR',
MUIA_Window_Menustrip, MakeMenustrip(prefsmenu),
MUIA_Window_ScreenTitle, COPYRIGHT,
MUIA_HelpNode, "PrefsWindow",
WindowContents,
VGroup,
Child,REG_Prefs=RegisterGroup(titles),
MUIA_Register_Frame, TRUE,
Child, HGroup,
Child, GP_Speed[0]=ColGroup(3),
End,
Child, MUI_MakeObject(MUIO_VBar,0),
Child, GP_Speed[1]=ColGroup(3),
End,
End,
Child, HGroup,
Child, GP_MPG[0]=ColGroup(3),
End,
Child, MUI_MakeObject(MUIO_VBar,0),
Child, GP_MPG[1]=ColGroup(3),
End,
End,
Child, ColGroup(2),
Child,KeyLabel2("Measurement",'m'),
Child,CY_Measure=CycleObject,
MUIA_Cycle_Entries,measurelabels,
MUIA_ControlChar,'m',
MUIA_ExportID, 30,
MUIA_Cycle_Active,MeasureUnits,
End,
Child,KeyLabel2("Display",'i'),
Child,CY_Display=CycleObject,
MUIA_Cycle_Entries,displaylabels,
MUIA_ControlChar,'i',
MUIA_ExportID, 33,
MUIA_Cycle_Active,DisplayType,
End,
Child,KeyLabel2("Default Fuel Efficiency",'f'),
Child, HGroup,
Child,ST_DefaultMPG=StringObject,
StringFrame,
MUIA_String_MaxLen, 5,
MUIA_String_Integer, DefaultMPG,
MUIA_String_Accept, "0123456789",
MUIA_String_Format, MUIV_String_Format_Right,
MUIA_ControlChar, 'f',
MUIA_ExportID, 31,
End,
Child,LB_DefaultMPG=DLabel(mpgabbrevs[MeasureUnits]),
End,
Child,KeyLabel2("Default Database",'d'),
Child,POP_DBase=PopaslObject,
MUIA_Popstring_String,ST_DBase=StringObject,
StringFrame,
MUIA_ControlChar, 'd',
MUIA_String_MaxLen, 255,
MUIA_String_Contents, DBase,
MUIA_ExportID, 32,
End,
MUIA_Popstring_Button,BT_DBase=PopButton(MUII_PopFile),
ASLFR_TitleText, "Choose a database file...",
End,
Child,HSpace(0),
Child,HGroup,
Child, CB_Debug=KeyCheckMark(debugoutput,'b'),
Child, KeyLLabel1("Debug output",'b'),
Child, HSpace(0),
End,
End,
End,
Child,HGroup,
MUIA_Group_SameSize, TRUE,
Child,BT_SavePrefs=KeyButton("Save",'s'),
Child,BT_UsePrefs=KeyButton("Use",'u'),
Child,BT_CancelPrefs=KeyButton("Cancel",'c'),
End,
End,
End,
End;
if(!app)
{
MUI_Request(NULL,NULL,0,NULL,"Ok","Could not create application.");
exit(20);
}
for(i=0;i<ROUTETYPES;i++)
{ // Add the speed gadgets
DoStuff(i,i/(ROUTETYPES/2));
}
DoMethod((ULONG *)mainwindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
DoMethod((ULONG *)prefswindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
app,2,MUIM_Application_ReturnID,CANCELPREFS);
DoMethod(LI_ViaList,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
app,2,MUIM_Application_ReturnID,VIALIST);
DoMethod(LV_ViaList,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
app,2,MUIM_Application_ReturnID,CHANGECITY);
ButtonBehave(BT_FromCity, FROMCITY);
ButtonBehave(BT_ToCity, TOCITY);
ButtonBehave(BT_AddCity, ADDCITY);
ButtonBehave(BT_ChangeCity, CHANGECITY);
ButtonBehave(BT_RemoveCity, REMOVECITY);
ButtonBehave(BT_MoveUp, MOVEUP);
ButtonBehave(BT_MoveDown, MOVEDOWN);
ButtonBehave(BT_DoRoute, DOROUTE);
ButtonBehave(BT_Quit, QUIT);
ButtonBehave(BT_SavePrefs, SAVEPREFS);
ButtonBehave(BT_UsePrefs, USEPREFS);
ButtonBehave(BT_CancelPrefs, CANCELPREFS);
// StringBehave(ST_DBase, DBASECHANGED);
DoMethod((ULONG *)app,MUIM_Application_Load,
MUIV_Application_Load_ENV);
get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
CycleBehave(CY_Measure, MEASURECHANGE);
DoMethod((ULONG *)mainwindow,MUIM_Window_SetCycleChain,
LV_ViaList, BT_MoveUp, BT_MoveDown,NULL);
scc=malloc(4*((2*ROUTETYPES)+7));
if(!scc)
{
MUI_Request(NULL,NULL,0,NULL,"Ok","Could not create application.");
exit(20);
}
for(i=0;i<ROUTETYPES;i++)
{
scc->obj[i]=ST_Speed[i];
scc->obj[i+ROUTETYPES]=ST_MPG[i];
}
i=ROUTETYPES*2;
scc->obj[i++]=CY_Measure;
scc->obj[i++]=CY_Display;
scc->obj[i++]=ST_DefaultMPG;
scc->obj[i++]=ST_DBase;
scc->obj[i++]=BT_DBase;
scc->obj[i]=NULL;
scc->id=MUIM_Window_SetCycleChain;
DoMethodA(prefswindow,scc);
free(scc);
set(BT_DoRoute,MUIA_Disabled,TRUE);
set(BT_MoveUp,MUIA_Disabled,TRUE);
set(BT_MoveDown,MUIA_Disabled,TRUE);
set(BT_ChangeCity,MUIA_Disabled,TRUE);
set(BT_RemoveCity,MUIA_Disabled,TRUE);
set(BT_AddCity,MUIA_Disabled,TRUE);
set(LV_ViaList,MUIA_Disabled,TRUE);
set(mainwindow,MUIA_Window_DefaultObject,LV_ViaList);
if(argc>1)
{
tempstr=argv[argc-1];
}
else
{
get(ST_DBase,MUIA_String_Contents,&tempstr);
}
ok=OpenDatabase(tempstr,&cd,&rd);
if(!ok)
{
MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't open database\n%s",tempstr);
strcpy(CurrentDBase,"No database loaded");
}
else
{
if(dbi)
{
if(Stricmp(dbi->dbi_Author,""))
fullinfo=TRUE;
}
strcpy(CurrentDBase,tempstr);
}
set(mainwindow,MUIA_Window_Open,TRUE);
get(mainwindow,MUIA_Window_Open,&i);
if(!i)
{
MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't open main window.");
exit(20);
}
while(going)
{
switch(DoMethod(app,MUIM_Application_Input,&sigs))
{ // Can't ignore MUIV_Application_ReturnID_Quit
case 0:
break;
case MUIV_Application_ReturnID_Quit:
going=FALSE;
break;
case ABOUT:
MUI_Request(app,mainwindow,0,NULL,(char *)"_Ok",
(char *)MUIX_C""
VERS" ("DATE")\n\n"
"A Highway Trip Planner based on\n"
"Jim Butterfield's "MUIX_U"RoadRoute"MUIX_N"\n\n"
"Modifications © 1994 Chris Lawrence\n"
"Freely redistributable\n\n"
"This application uses MUI\n"
"MUI is © 1993-94 Stefan Stuntz\n\n"
"Compiled on "__DATE__);
break;
case INFO:
if(fullinfo)
{
MUI_Request(app,mainwindow,0,NULL,"_Ok",
"Database Information\n\n"
MUIX_PH"%s\n"MUIX_PT
"%ld Cities, %ld Routes\n\n"
"Written by:\n"
"%s (%s)",CurrentDBase,cdcount,rdcount,
dbi->dbi_Author,dbi->dbi_EMail);
}
else
{
MUI_Request(app,mainwindow,0,NULL,"_Ok",
"Database Information\n\n"
MUIX_PH"%s\n"MUIX_PT
"%ld Cities, %ld Routes",CurrentDBase,cdcount,rdcount);
}
break;
case PREFS:
set(prefswindow,MUIA_Window_Open,TRUE);
get(prefswindow,MUIA_Window_Open,&i);
if(!i)
{
MUI_Request(app,mainwindow,0,NULL,"_Ok",
"Can't open Preferences window.");
}
break;
case SAVEPREFS: // Do not break up
DoMethod((ULONG *)app,MUIM_Application_Save,
MUIV_Application_Save_ENVARC);
case USEPREFS: // Do not break up
DoMethod((ULONG *)app,MUIM_Application_Save,
MUIV_Application_Save_ENV);
set(prefswindow,MUIA_Window_Open,FALSE);
break;
case CANCELPREFS:
DoMethod((ULONG *)app,MUIM_Application_Load,
MUIV_Application_Load_ENV);
set(prefswindow,MUIA_Window_Open,FALSE);
break;
case HIDE:
set(app,MUIA_Application_Iconified,TRUE);
break;
case OPEN:
if(GetFile(filename,FALSE,"Select new database..."))
{
strcpy(CurrentDBase,filename);
ok=OpenDatabase(CurrentDBase,&cd,&rd);
if(!ok)
{
MUI_Request(app,mainwindow,0,NULL,"_Ok",
"Couldn't open database\n%s",filename);
}
else
{
from=-1;
to=-1;
for(i=0;i<MAXVIA;i++)
via[i]=-1;
viacount=0;
set(TX_FromCity,MUIA_Text_Contents,"");
set(TX_ToCity,MUIA_Text_Contents,"");
DoMethod(LI_ViaList,MUIM_List_Clear,NULL);
set(BT_DoRoute,MUIA_Disabled,TRUE);
set(BT_AddCity,MUIA_Disabled,TRUE);
set(LV_ViaList,MUIA_Disabled,TRUE);
if(dbi)
{
if(Stricmp(dbi->dbi_Author,""))
fullinfo=TRUE;
}
}
}
break;
case OPENPREFS:
if(GetFile(filename,FALSE,"Select a preferences file..."))
{
DoMethod((ULONG *)app,MUIM_Application_Load,filename);
}
break;
case SAVEPREFSAS:
if(GetFile(filename,TRUE,"Save preferences as..."))
{
DoMethod((ULONG *)app,MUIM_Application_Save,filename);
}
break;
case RESTOREPREFS:
DoMethod((ULONG *)app,MUIM_Application_Load,
MUIV_Application_Load_ENV);
get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
break;
case LASTSAVEDPREFS:
DoMethod((ULONG *)app,MUIM_Application_Load,
MUIV_Application_Load_ENVARC);
get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
break;
case RESETPREFS:
for(i=0;i<ROUTETYPES;i++)
{
setinteger(ST_Speed[i],DefSpeed[i]);
setinteger(ST_MPG[i],DefMPG[i]);
}
setstring(ST_DBase,DefDBase);
setinteger(ST_DefaultMPG,DefDefaultMPG);
set(CY_Measure,MUIA_Cycle_Active,DefMeasureUnits);
MeasureUnits=DefMeasureUnits;
setcycle(CY_Display,DefDisplayType);
break;
case FROMCITY:
i=ChooseCity(cd,cdcount,from,"Choose starting city...");
if(i==(ULONG)-2)
DoMethod(app,MUIM_Application_ReturnID,QUIT);
if(i<(ULONG)-2)
{
from=i;
SPrintf(filename,"%s, %s",cd[from].CityName,cd[from].StateName);
set(TX_FromCity,MUIA_Text_Contents,filename);
}
set(BT_DoRoute,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
set(BT_AddCity,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
break;
case TOCITY:
i=ChooseCity(cd,cdcount,to,"Choose ending city...");
if(i==(ULONG)-2)
DoMethod(app,MUIM_Application_ReturnID,QUIT);
if(i<(ULONG)-2)
{
to=i;
SPrintf(filename,"%s, %s",cd[to].CityName,cd[to].StateName);
set(TX_ToCity,MUIA_Text_Contents,filename);
}
set(BT_DoRoute,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
set(BT_AddCity,MUIA_Disabled,(from==(ULONG)-1 || to==(ULONG)-1));
break;
case DOROUTE:
if(from==to && viacount==0)
{
MUI_Request(app,mainwindow,0,NULL,"_Ok",
"You must travel through at least two cities.");
}
else
{
for(i=0;i<ROUTETYPES;i++)
{
get(ST_Speed[i],MUIA_String_Integer,&Speed[i]);
get(ST_MPG[i],MUIA_String_Integer,&MPG[i]);
}
get(ST_DefaultMPG,MUIA_String_Integer,&DefaultMPG);
get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
get(CY_Display,MUIA_Cycle_Active,&DisplayType);
get(CB_Debug,MUIA_Selected,&debugoutput);
if(NavCoord(cd,rd,from,to,via,viacount)) going=FALSE;
}
break;
case VIALIST:
get(LI_ViaList,MUIA_List_Active,&i);
set(BT_ChangeCity,MUIA_Disabled,(i==MUIV_List_Active_Off));
set(BT_RemoveCity,MUIA_Disabled,(i==MUIV_List_Active_Off));
set(BT_MoveUp,MUIA_Disabled,(i==MUIV_List_Active_Off || i==0));
set(BT_MoveDown,MUIA_Disabled,(i==MUIV_List_Active_Off || i==viacount-1));
break;
case ADDCITY:
if(viacount<MAXVIA)
{
via[viacount]=ChooseCity(cd,cdcount,-1,"Choose `via' city...");
if(via[viacount]==(ULONG)-2)
DoMethod(app,MUIM_Application_ReturnID,QUIT);
if(via[viacount]<(ULONG)-2)
{
DoMethod(LI_ViaList,MUIM_List_InsertSingle,&cd[via[viacount]],
MUIV_List_Insert_Bottom);
DoMethod(app,MUIM_Application_ReturnID,VIALIST);
set(LV_ViaList,MUIA_Disabled,FALSE);
viacount++;
}
}
else
MUI_Request(app,mainwindow,0,NULL,"_Ok","There is a maximum of\n"
"%ld `via' destinations.",MAXVIA);
break;
case CHANGECITY:
get(LI_ViaList,MUIA_List_Active,&temp);
if(temp!=MUIV_List_Active_Off)
{
i=ChooseCity(cd,cdcount,via[temp],"Choose `via' city...");
if(i==(ULONG)-2)
DoMethod(app,MUIM_Application_ReturnID,QUIT);
if(i<(ULONG)-2)
{
DoMethod(LI_ViaList,MUIM_List_Remove,temp);
DoMethod(LI_ViaList,MUIM_List_InsertSingle,&cd[i],temp);
via[temp]=i;
set(LI_ViaList,MUIA_List_Active,temp);
}
}
break;
case REMOVECITY:
get(LI_ViaList,MUIA_List_Active,&temp);
if(temp!=MUIV_List_Active_Off)
{
DoMethod(LI_ViaList,MUIM_List_Remove,temp);
for(i=temp+1;i<viacount;i++)
via[i-1]=via[i];
via[viacount-1]=-1;
viacount--;
if(!viacount) set(LV_ViaList,MUIA_Disabled,TRUE);
}
break;
case MOVEUP:
get(LI_ViaList,MUIA_List_Active,&temp);
if(temp!=MUIV_List_Active_Off && temp>0)
{
DoMethod(LI_ViaList,MUIM_List_Exchange,temp,temp-1);
i=via[temp];
via[temp]=via[temp-1];
via[temp-1]=i;
set(LI_ViaList,MUIA_List_Active,temp-1);
}
break;
case MOVEDOWN:
get(LI_ViaList,MUIA_List_Active,&temp);
if(temp!=MUIV_List_Active_Off && temp<viacount-1)
{
DoMethod(LI_ViaList,MUIM_List_Exchange,temp,temp+1);
i=via[temp];
via[temp]=via[temp+1];
via[temp+1]=i;
set(LI_ViaList,MUIA_List_Active,temp+1);
}
break;
case MEASURECHANGE:
OldUnits=MeasureUnits;
get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
get(CY_Measure,MUIA_Cycle_Active,&MeasureUnits);
get(ST_DefaultMPG,MUIA_String_Integer,&DefaultMPG);
DefaultMPG=ConvertEfficiency(DefaultMPG,OldUnits,MeasureUnits);
set(ST_DefaultMPG,MUIA_String_Integer,DefaultMPG);
set(LB_DefaultMPG,MUIA_Text_Contents,mpgabbrevs[MeasureUnits]);
for(i=0;i<ROUTETYPES;i++)
{
get(ST_Speed[i],MUIA_String_Integer,&Speed[i]);
get(ST_MPG[i],MUIA_String_Integer,&MPG[i]);
Speed[i]=ConvertDist(Speed[i],OldUnits,MeasureUnits);
MPG[i]=ConvertEfficiency(MPG[i],OldUnits,MeasureUnits);
set(ST_Speed[i],MUIA_String_Integer,Speed[i]);
set(ST_MPG[i],MUIA_String_Integer,MPG[i]);
set(LB_Speed[i],MUIA_Text_Contents,speedabbrevs[MeasureUnits]);
set(LB_MPG[i],MUIA_Text_Contents,mpgabbrevs[MeasureUnits]);
}
break;
}
if(going && sigs) sigs=Wait(sigs | SIGBREAKF_CTRL_C);
if(sigs & SIGBREAKF_CTRL_C) going=FALSE;
}
set(prefswindow,MUIA_Window_Open,FALSE);
set(mainwindow,MUIA_Window_Open,FALSE);
exit(0);
}
BOOL GetFile(char *filename, BOOL saverequest, char *tbar)
{
struct FileRequester *fr;
struct Window *win;
BOOL result;
fr=MUI_AllocAslRequest(ASL_FileRequest,NULL);
if(!fr) return FALSE;
get(mainwindow,MUIA_Window_Window,&win);
set(app,MUIA_Application_Sleep,TRUE);
if(MUI_AslRequestTags(fr,
ASLFR_Window, win,
ASLFR_TitleText, tbar,
ASLFR_Flags1, (saverequest ? FRF_DOSAVEMODE : 0),
ASLFR_RejectIcons, TRUE,
TAG_DONE))
{
strcpy(filename,fr->fr_Drawer);
AddPart(filename,fr->fr_File,255);
result=TRUE;
}
else
{
result=FALSE;
}
set(app,MUIA_Application_Sleep,FALSE);
if(fr) MUI_FreeAslRequest(fr);
return result;
}
BOOL OpenDatabase(char *filename, struct CityData **cd,
struct RouteData **rd)
{
APTR oldmemptr;
BPTR fhandle;
__aligned struct FileInfoBlock fib;
ULONG *temp, i, col;
fhandle=Open(filename,MODE_OLDFILE);
if(!fhandle) return FALSE;
if(!ExamineFH(fhandle,&fib))
{
Close(fhandle);
return FALSE;
}
oldmemptr=memptr;
memptr=malloc(fib.fib_Size);
if(!memptr)
{
Close(fhandle);
return FALSE;
}
if(app)
{
set(app,MUIA_Application_Sleep,TRUE);
}
FRead(fhandle,memptr,1,fib.fib_Size);
Close(fhandle);
temp=(ULONG *)memptr;
if((*temp)!='RPL2')
{
if(app)
{
set(app,MUIA_Application_Sleep,FALSE);
}
return FALSE;
}
if(oldmemptr) free(oldmemptr);
*cd=(struct CityData *)((char *)memptr+12);
temp=(ULONG *)((char *)(*cd)-4);
cdcount=*temp;
*rd=(struct RouteData *)
((char *)memptr+(sizeof(struct CityData)*(cdcount)+20));
temp=(ULONG *)((char *)(*rd)-4);
rdcount=*temp;
// Parse the files
for(i=0;i<cdcount;i++)
(*cd)[i].RoadList=NULL;
for(i=0;i<rdcount;i++)
{
struct RouteData *Route;
Route=&((*rd)[i]);
for(col=0;col<2;col++)
{
struct CityData *FoundCity;
FoundCity=&((*cd)[Route->CityID[col]]);
Route->CityNum[col]=FoundCity;
Route->RLink[col]=FoundCity->RoadList;
Route->Colm[col]=FoundCity->Colum;
FoundCity->RoadList=Route;
FoundCity->Colum=col;
}
}
temp=(ULONG *)memptr;
dbi=(struct DataBaseInfo *)
((char *)memptr+(sizeof(struct CityData)*(cdcount)+
sizeof(struct RouteData)*(rdcount)+20));
if(app)
{
set(app,MUIA_Application_Sleep,FALSE);
}
if(dbi->dbi_Security!=DoFunkyThing(cdcount+rdcount+dbi->dbi_AuthorCode+
StringSum(dbi->dbi_Author)+StringSum(dbi->dbi_EMail)))
{
free(memptr);
memptr=NULL;
cdcount=0;
rdcount=0;
return FALSE;
}
return TRUE;
}
#define CANCEL (30)
#define OK (31)
#define STRING (32)
#define CHANGELV (33)
#define ALL (34)
ULONG ChooseCity(struct CityData *cd, ULONG CityCount, ULONG CurrentCity,
char *tbar)
{
// Present requester for choosing a city.
// Return -2 if quit request received.
// Return -1 if canceled
APTR citywindow, LV_Listview, BT_All, BT_Ok, BT_Cancel, ST_CityName;
APTR tempptr;
BOOL going=TRUE, exact;
ULONG sigs, choice, temp, i, found, entries;
static struct CityName *cn;
static char *tmp, cbuf[514], sbuf[128], compstr[256];
set(app,MUIA_Application_Sleep,TRUE);
citywindow=WindowObject,
MUIA_Window_Title, tbar,
MUIA_Window_ScreenTitle, COPYRIGHT,
MUIA_Window_RefWindow, mainwindow,
MUIA_Window_NoMenus, TRUE,
MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Moused,
MUIA_Window_TopEdge, MUIV_Window_TopEdge_Moused,
MUIA_Window_Height, MUIV_Window_Height_Default,
MUIA_HelpNode, "CityRequester",
WindowContents,
VGroup,
Child,LV_Listview=ListviewObject,
MUIA_Listview_List,ListObject,
MUIA_List_CompareHook, &comphook,
MUIA_List_ConstructHook, &consthook,
MUIA_List_DestructHook, &desthook,
MUIA_List_DisplayHook, &disphook,
MUIA_List_AdjustWidth, TRUE,
InputListFrame,
End,
MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_None,
End,
Child,HGroup,
Child, KeyLLabel2("Search:",'s'),
Child, ST_CityName=KeyString("",70,'s'),
Child, BT_All=KeyButton("All",'a'),
End,
Child,HGroup,
Child, BT_Ok=KeyButton("Ok",'o'),
Child, BT_Cancel=KeyButton("Cancel",'c'),
MUIA_Group_SameSize, TRUE,
End,
End,
End;
if(citywindow)
{
DoMethod(app,OM_ADDMEMBER,citywindow);
DoMethod(citywindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
app,2,MUIM_Application_ReturnID,CANCEL);
DoMethod(LV_Listview,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
app,2,MUIM_Application_ReturnID,OK);
ButtonBehave(BT_Ok, OK);
ButtonBehave(BT_All, ALL);
ButtonBehave(BT_Cancel, CANCEL);
DoMethod(LV_Listview,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
app,2,MUIM_Application_ReturnID,CHANGELV);
// Add entries to list & sort them
for(i=0;i<CityCount;i++)
cd[i].Displayed=TRUE;
AddListEntries(LV_Listview,cd,CityCount);
if(CurrentCity==(ULONG)-1)
{
set(LV_Listview,MUIA_List_Active,MUIV_List_Active_Off);
set(BT_Ok,MUIA_Disabled,TRUE);
}
else
{
BOOL found=FALSE;
for(i=0;i<cdcount && !found;i++)
{
DoMethod(LV_Listview,MUIM_List_GetEntry,i,&cn);
if(cn->cn_CityID==CurrentCity)
{
found=TRUE;
set(LV_Listview,MUIA_List_Active,i);
}
}
}
DoMethod(citywindow,MUIM_Window_SetCycleChain,ST_CityName,
LV_Listview,NULL);
set(citywindow,MUIA_Window_DefaultObject,LV_Listview);
set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
set(ST_CityName,MUIA_String_AttachedList,LV_Listview);
StringBehave(ST_CityName,OK);
set(citywindow,MUIA_Window_Open,TRUE);
DoMethod(LV_Listview,MUIM_List_Jump,MUIV_List_Jump_Active);
while(going)
{
switch(DoMethod(app,MUIM_Application_Input,&sigs))
{ // Can't ignore MUIV_Application_ReturnID_Quit
case MUIV_Application_ReturnID_Quit:
choice=(ULONG)-2;
going=FALSE;
break;
case CANCEL:
choice=(ULONG)-1;
going=FALSE;
break;
case CHANGELV:
get(LV_Listview,MUIA_List_Active,&temp);
set(BT_Ok,MUIA_Disabled,(temp==MUIV_List_Active_Off));
if(temp!=MUIV_List_Active_Off)
{
DoMethod(LV_Listview,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,
&cn);
setstring(ST_CityName,cn->cn_Name);
}
break;
case STRING:
// Do search thingy
get(ST_CityName,MUIA_String_Contents,&tmp);
strcpy(cbuf,tmp);
get(LV_Listview,MUIA_List_Entries,&entries);
set(LV_Listview,MUIA_List_Active,MUIV_List_Active_Off);
if(tmp=strchr(cbuf,','))
{
*tmp++='\0';
while(*tmp==' ') tmp++;
strcpy(sbuf,tmp);
}
else strcpy(sbuf,"");
SPrintf(compstr,"%s#?,# %s#?",cbuf,sbuf);
ParsePatternNoCase(compstr,cbuf,514);
if(Stricmp(compstr,"#?,# #?"))
{
for(found=0,i=0,exact=FALSE;i<entries;i++)
{
DoMethod(LV_Listview,MUIM_List_GetEntry,i,&cn);
if(cn)
{
if(MatchPatternNoCase(cbuf,cn->cn_Name))
{
cd[cn->cn_CityID].Displayed=TRUE;
found++;
choice=i;
get(ST_CityName,MUIA_String_Contents,&tmp);
if(!Stricmp(tmp,cn->cn_Name))
{
exact=TRUE;
temp=i;
}
}
else
cd[cn->cn_CityID].Displayed=FALSE;
}
}
}
else
{
for(i=0;i<CityCount;i++)
cd[i].Displayed=TRUE;
found=2;
}
if(found==0)
{
setstring(ST_CityName,"");
MUI_Request(app,citywindow,0,NULL,"_Ok","No cities matched");
set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
}
else if(found==1 || exact)
{
set(LV_Listview,MUIA_List_Active,(exact ? temp : choice));
if(exact)
{
DoMethod(app,MUIM_Application_ReturnID,OK);
set(citywindow,MUIA_Window_ActiveObject,LV_Listview);
}
else
set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
}
else
{
AddListEntries(LV_Listview,cd,CityCount);
set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
}
break;
case ALL:
for(i=0;i<CityCount;i++)
{
cd[i].Displayed=TRUE;
}
AddListEntries(LV_Listview,cd,CityCount);
set(citywindow,MUIA_Window_ActiveObject,ST_CityName);
break;
case OK:
get(citywindow,MUIA_Window_ActiveObject,&tempptr);
if(tempptr==ST_CityName)
{
DoMethod(app,MUIM_Application_ReturnID,STRING);
}
else
{
DoMethod(LV_Listview,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&cn);
if(cn)
{
get(ST_CityName,MUIA_String_Contents,&tmp);
if(!Stricmp(cn->cn_Name,tmp))
{
choice=cn->cn_CityID;
going=FALSE;
}
else
{
DoMethod(app,MUIM_Application_ReturnID,STRING);
}
}
}
break;
}
if(going && sigs) Wait(sigs);
}
set(citywindow,MUIA_Window_Open,FALSE);
DoMethod(app,OM_REMMEMBER,citywindow);
MUI_DisposeObject(citywindow);
}
else
MUI_RequestA(app,mainwindow,0,NULL,"_Ok","Couldn't create city requester.",NULL);
set(app,MUIA_Application_Sleep,FALSE);
return(choice);
}
void AddListEntries(APTR list, struct CityData *cd, ULONG CityCount)
{
ULONG i;
set(list,MUIA_List_Quiet,TRUE);
DoMethod(list,MUIM_List_Clear,NULL);
for(i=0;i<CityCount;i++)
if(cd[i].Displayed && !cd[i].Intersection)
DoMethod(list,MUIM_List_InsertSingle,&cd[i],MUIV_List_Insert_Bottom);
DoMethod(list,MUIM_List_Sort,NULL);
set(list,MUIA_List_Quiet,FALSE);
}
UWORD ConvertDist(UWORD srcDist, UWORD srcUnits, UWORD destUnits);
UWORD ConvertToTime(UWORD Code, UWORD SVal, UWORD Dist, UWORD RteUnits,
UWORD SysUnits);
UWORD ConvertDist(UWORD srcDist, UWORD srcUnits, UWORD destUnits)
{
ULONG work;
if(srcUnits==UNITS_ENGLISH && destUnits==UNITS_METRIC)
{
work=(srcDist*16093)+8047;
work/=10000;
}
else if(srcUnits==UNITS_METRIC && destUnits==UNITS_ENGLISH)
{
work=(srcDist*10000)+5000;
work/=16093;
}
else work=srcDist;
return (UWORD)work;
}
UWORD ConvertToTime(UWORD Code, UWORD SVal, UWORD Dist, UWORD RteUnits,
UWORD SysUnits)
{
float tval;
if(Code==USE_TIME) return SVal;
if(Code==USE_SPEED)
{
if(SVal==0) return 0;
tval=60.0*Dist/SVal;
}
else
{
tval=60.0*ConvertDist(Dist,RteUnits,SysUnits)/Speed[Code-2];
}
return(UWORD)ceil(tval);
}
UWORD ConvertEfficiency(UWORD srcEff, UWORD srcUnits, UWORD destUnits)
{
ULONG work;
if(srcUnits==UNITS_ENGLISH && destUnits==UNITS_METRIC)
{
work=(srcEff*4251)+2126;
work/=10000;
}
else if(srcUnits==UNITS_METRIC && destUnits==UNITS_ENGLISH)
{
work=(srcEff*10000)+5000;
work/=4251;
}
else work=srcEff;
return (UWORD)work;
}
// Trip stuff
#define VIEW_SAVEAS (40) // Save the trip to disk
#define VIEW_PRINT (41) // Print the trip
#define VIEW_CLOSE (42) // Close the window
#define VIEW_QUIT MUIV_Application_ReturnID_Quit
#define VIEW_TRIPCHNG (43) // If user changes viewed trip
#define VIEW_CONTINUE VIEW_CLOSE
struct NewMenu viewmenu[]={
NM_TITLE,"Project",NULL,NULL,0L,NULL,
NM_ITEM,"Save As...","S",NULL,0L,(APTR)VIEW_SAVEAS,
NM_ITEM,"Print","P",NULL,0L,(APTR)VIEW_PRINT,
NM_ITEM,NM_BARLABEL,NULL,NULL,0L,NULL,
NM_ITEM,"Close Window","C",NULL,0L,(APTR)VIEW_CLOSE,
NM_ITEM,"Quit RoutePlanner","Q",NULL,0L,(APTR)VIEW_QUIT,
};
static char *triptypes[]={"shortest route","quickest route",NULL};
void PrintRoute(char *filename, struct CityData **point, UWORD points,
BOOL isprinter);
BOOL NavCoord(struct CityData *cd, struct RouteData *rd,
ULONG fromID, ULONG toID, ULONG *viaID, ULONG viacount)
//
// Navigation Coordination routine
{
BOOL wasquit=FALSE, going=TRUE;
struct CityData *point[MAXVIA+2], *SearchCity, *FLink;
ULONG i, points, sigs;
APTR navwindow;
unsigned short Column, ColStart, ColEnd, TrackTrail;
unsigned short NextCol, NewCol;
struct RouteData *NextRoute, *NewRoute;
static unsigned short Result[3][2];
static char strbuff[300], tempstr[300], otstr[300];
static struct TripEntry te;
APTR TX_From,TX_To,TX_Via,VG_Trip[2];
APTR CY_ChangeTrip,TX_Distance[2],TX_Time[2],TX_Fuel[2];
APTR BT_Continue,GP_Trip,LB_Via;
// Sleep windows
set(app,MUIA_Application_Sleep,TRUE);
for(i=0;i<MAXTRAIL;i++)
{
for(Column=0;Column<2;Column++)
{
Trail[i][Column].ct_City=NULL;
Trail[i][Column].ct_Waypoint=CT_NOPOINT;
}
}
// How many waypoints?
point[0]=&cd[fromID];
for(i=1;i<(viacount+1) && viaID[i-1]!=(ULONG)-1;i++)
{
point[i]=&cd[viaID[i-1]];
}
point[i]=&cd[toID];
points=i+1;
// Do navigation, with via list
TrailPoint[0]=0;
TrailPoint[1]=0;
for(i=0;i<(points-1);i++)
{
Navigate(cd,point[i],point[i+1]);
for(Column=0;Column<2;Column++)
{
if(TrailPoint[Column])
Trail[TrailPoint[Column]-1][Column].ct_Waypoint=CT_WAYPOINT;
}
}
for(Column=0; Column<2; Column++)
{
Result[0][Column]=0; /* dist */
Result[1][Column]=0; /* time */
Result[2][Column]=0; // fuel
SearchCity=point[0];
for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
{
ULONG mpg, truedist, truetime;
FLink=Trail[TrackTrail][Column].ct_City;
NextRoute=SearchCity->RoadList;
NextCol=SearchCity->Colum;
while (NextRoute && FLink != NextRoute->CityNum[1-NextCol])
{
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
}
if(NextRoute->SpeedCode>=INTERSTATE_RURAL)
mpg=MPG[NextRoute->SpeedCode-2];
else
mpg=DefaultMPG;
truedist=ConvertDist(NextRoute->Distance,NextRoute->Units,
MeasureUnits);
truetime=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
NextRoute->Distance,NextRoute->Units,MeasureUnits);
Result[2][Column]=Result[2][Column]+(((100*truedist)/mpg)+50)/100;
Result[1][Column]=Result[1][Column]+truetime;
Result[0][Column]=Result[0][Column]+truedist;
SearchCity=FLink;
} /* next Link */
} /* next Column */
ColStart=0;
ColEnd=1;
if(Result[0][0]==Result[0][1])
{
ColStart=1;
ColEnd=1;
}
if(Result[1][0]==Result[1][1])
{
ColStart=0;
ColEnd=0;
}
// Pop up a view window
navwindow=WindowObject,
MUIA_Window_Title, "RoutePlanner Trip",
MUIA_Window_ScreenTitle, COPYRIGHT,
MUIA_Window_ID, 3,
MUIA_Window_Menustrip, MakeMenustrip(viewmenu),
MUIA_HelpNode, "TripWindow",
WindowContents,
VGroup,
Child,ColGroup(2),
Child,Label2("From:"),
Child,TX_From=SimpleText(""),
Child,Label2("To:"),
Child,TX_To=SimpleText(""),
Child,LB_Via=Label2("Via:"),
Child,TX_Via=SimpleText(""),
End,
Child,VGroup,
GroupFrame,
Child,HGroup,
Child,KeyLLabel2("View",'v'),
Child,CY_ChangeTrip=KeyCycle(triptypes,'v'),
End,
Child,GP_Trip=VGroup,
MUIA_Group_PageMode, TRUE,
Child,VGroup,
Child,ColGroup(2),
Child,Label2("Distance:"),
Child,TX_Distance[0]=SimpleText(""),
Child,Label2("Time:"),
Child,TX_Time[0]=SimpleText(""),
Child,Label2("Fuel used:"),
Child,TX_Fuel[0]=SimpleText(""),
End,
Child,VG_Trip[0]=ListviewObject,
MUIA_Listview_Input, FALSE,
MUIA_Listview_List, ListObject,
ReadListFrame,
MUIA_Font, MUIV_Font_Fixed,
MUIA_List_ConstructHook, MUIV_List_ConstructHook_String,
MUIA_List_DestructHook, MUIV_List_DestructHook_String,
End,
End,
End,
Child,VGroup,
Child,ColGroup(2),
Child,Label2("Distance:"),
Child,TX_Distance[1]=SimpleText(""),
Child,Label2("Time:"),
Child,TX_Time[1]=SimpleText(""),
Child,Label2("Fuel used:"),
Child,TX_Fuel[1]=SimpleText(""),
End,
Child,VG_Trip[1]=ListviewObject,
MUIA_Listview_Input, FALSE,
MUIA_Listview_List, ListObject,
ReadListFrame,
MUIA_Font, MUIV_Font_Fixed,
MUIA_List_ConstructHook, MUIV_List_ConstructHook_String,
MUIA_List_DestructHook, MUIV_List_DestructHook_String,
End,
End,
End,
End,
End,
Child,BT_Continue=KeyButton("Continue",'c'),
End,
End;
if(!navwindow)
{
MUI_Request(app,mainwindow,0,NULL,"_Ok","Couldn't open trip window.");
return FALSE;
}
DoMethod(app,OM_ADDMEMBER,navwindow);
SPrintf(strbuff,"%s, %s",point[0]->CityName,point[0]->StateName);
set(TX_From,MUIA_Text_Contents,strbuff);
SPrintf(strbuff,"%s, %s",point[points-1]->CityName,
point[points-1]->StateName);
set(TX_To,MUIA_Text_Contents,strbuff);
if(points>2)
{
strcpy(strbuff,"");
for(i=1;i<(points-1);i++)
{
SPrintf(tempstr,"%s, %s",point[i]->CityName,point[i]->StateName);
strncat(strbuff,tempstr,sizeof(strbuff));
if(i<(points-2)) strncat(strbuff,"\n",sizeof(strbuff));
}
set(TX_Via,MUIA_Text_Contents,strbuff);
}
else
{
set(TX_Via,MUIA_Text_Contents,"Most direct route");
}
for(Column=ColStart; Column<=ColEnd; Column++)
{
UWORD dist=0, time=0, cumdist=0, cumtime=0;
SearchCity=point[0];
for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
{
FLink=Trail[TrackTrail][Column].ct_City;
NextRoute=SearchCity->RoadList;
NextCol=SearchCity->Colum;
while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol])
{
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
} /* wend, no NextRoute */
/* Print highway link information */
te.te_Distance=ConvertDist(NextRoute->Distance,NextRoute->Units,
MeasureUnits);
te.te_Time=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
NextRoute->Distance,NextRoute->Units,MeasureUnits);
te.te_Route=NextRoute->Hiway;
if(Stricmp(NextRoute->Exits[1-NextCol],""))
{
SPrintf(tempstr,"%s (Exit %s)",FLink->CityName,
NextRoute->Exits[1-NextCol]);
te.te_End=tempstr;
}
else te.te_End=FLink->CityName;
dist+=te.te_Distance;
time+=te.te_Time;
cumdist+=te.te_Distance;
cumtime+=te.te_Time;
if(Stricmp(SearchCity->StateName,FLink->StateName))
{
SPrintf(otstr,"CROSSING FROM %s TO %s",SearchCity->StateName,
FLink->StateName);
DoMethod(VG_Trip[Column],MUIM_List_InsertSingle,otstr,
MUIV_List_Insert_Bottom);
}
if(TrackTrail+1<TrailPoint[Column] && DisplayType &&
!Trail[TrackTrail][Column].ct_Waypoint)
{
NextRoute=FLink->RoadList;
NextCol=FLink->Colum;
FLink=Trail[TrackTrail+1][Column].ct_City;
while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol])
{
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
} /* wend, no NextRoute */
FLink=Trail[TrackTrail][Column].ct_City;
if(DisplayType==DIS_ROUTECHANGE)
{
if(!Stricmp(NextRoute->Hiway,te.te_Route))
{
SearchCity=FLink;
continue;
}
}
if(DisplayType==DIS_STATECHANGE)
{
if(!Stricmp(FLink->StateName,SearchCity->StateName) &&
!Stricmp(NextRoute->Hiway,te.te_Route))
{
SearchCity=FLink;
continue;
}
}
}
SPrintf(otstr,"%4ld %s (%2ld:%02ld) [%4ld %s (%2ld:%02ld)] %s to %s",
dist,distabbrevs[MeasureUnits],time/60,time%60,
cumdist,distabbrevs[MeasureUnits],cumtime/60,cumtime%60,
te.te_Route,te.te_End);
DoMethod(VG_Trip[Column],MUIM_List_InsertSingle,otstr,
MUIV_List_Insert_Bottom);
if(Trail[TrackTrail][Column].ct_Waypoint)
{
SPrintf(otstr,"ARRIVED %s, %s: %ld %s%s - %ld:%02ld",
FLink->CityName,FLink->StateName,
cumdist,distnames[MeasureUnits],(cumdist==1 ? "" : "s"),
cumtime/60,cumtime%60);
DoMethod(VG_Trip[Column],MUIM_List_InsertSingle,otstr,
MUIV_List_Insert_Bottom);
cumdist=0;
cumtime=0;
}
dist=0;
time=0;
SearchCity=FLink;
} /* next link */
SPrintf(strbuff,"%ld %s%s",Result[0][Column],distnames[MeasureUnits],
(Result[0][Column]==1 ? "" : "s"));
set(TX_Distance[Column],MUIA_Text_Contents,strbuff);
SPrintf(strbuff,"%ld hour%s, %ld minute%s",Result[1][Column]/60,
((Result[1][Column]/60)==1 ? "" : "s"),
Result[1][Column]%60,((Result[1][Column]%60)==1 ? "" : "s"));
set(TX_Time[Column],MUIA_Text_Contents,strbuff);
SPrintf(strbuff,"%ld %s%s",Result[2][Column],fuelunits[MeasureUnits],
(Result[2][Column]==1 ? "" : "s"));
set(TX_Fuel[Column],MUIA_Text_Contents,strbuff);
} /* next Column */
ButtonBehave(BT_Continue,VIEW_CONTINUE);
DoMethod(navwindow,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
app,2,MUIM_Application_ReturnID,VIEW_CLOSE);
DoMethod(CY_ChangeTrip,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
GP_Trip,3,MUIM_Set,MUIA_Group_ActivePage,MUIV_TriggerValue);
for(i=ColStart;i<=ColEnd;i++)
DoMethod(CY_ChangeTrip,MUIM_Notify,MUIA_Cycle_Active,i,
navwindow,3,MUIM_Set,MUIA_Window_ActiveObject,VG_Trip[i]);
set(CY_ChangeTrip,MUIA_Cycle_Active,ColStart);
if(ColStart==ColEnd) set(CY_ChangeTrip,MUIA_Disabled,TRUE);
DoMethod(navwindow,MUIM_Window_SetCycleChain,VG_Trip[0],
VG_Trip[1],NULL);
set(navwindow,MUIA_Window_ActiveObject,VG_Trip[ColStart]);
set(navwindow,MUIA_Window_Open,TRUE);
// Window event loop
while(going)
{
switch(DoMethod(app,MUIM_Application_Input,&sigs))
{ // Can't ignore MUIV_Application_ReturnID_Quit
case MUIV_Application_ReturnID_Quit:
wasquit=TRUE;
going=FALSE;
break;
case VIEW_CLOSE:
going=FALSE;
break;
case VIEW_SAVEAS:
set(navwindow,MUIA_Window_Sleep,TRUE);
if(GetFile(strbuff,TRUE,"Save directions as..."))
{
PrintRoute(strbuff,point,points,FALSE);
}
set(navwindow,MUIA_Window_Sleep,FALSE);
break;
case VIEW_PRINT:
set(navwindow,MUIA_Window_Sleep,TRUE);
PrintRoute("PRT:",point,points,TRUE);
set(navwindow,MUIA_Window_Sleep,FALSE);
break;
}
if(going && sigs) Wait(sigs);
}
set(navwindow,MUIA_Window_Open,FALSE);
DoMethod(app,OM_REMMEMBER,navwindow);
MUI_DisposeObject(navwindow);
set(app,MUIA_Application_Sleep,FALSE);
return wasquit;
}
void Navigate(struct CityData *cd, struct CityData *Start,
struct CityData *Finish)
{
// This is almost straight out of Jim's code.
// Only thing different is the maximum trail length; RoutePlanner
// allows a much longer trail
ULONG i;
unsigned short Column, Travel;
unsigned short NextCol, NewCol;
struct CityData *BLink, *SearchCity;
struct CityData *ELink, *FLink, *OtherCity;
struct RouteData *NextRoute, *NewRoute;
static unsigned short MiniVal;
static unsigned short ThisDist[2];
for(i=0; i<cdcount; i++)
{
cd[i].WorkList = NULL;
for(Column=0; Column<2; Column++)
{
cd[i].MinDist[Column]=65535;
cd[i].NextCity[Column]=NULL;
}
}
ELink=Finish;
MiniVal=0;
for(Column=0; Column<2; Column++)
{
Finish->MinDist[Column]=0;
ThisDist[Column]=65535;
}
SearchCity=Finish;
while (SearchCity)
{
for(Column=0; Column<2; Column++)
{
if(SearchCity->MinDist[Column] < Start->MinDist[Column])
{
//if(Column==0 && debugoutput)
// Printf("Scanning map at range: %ld: %s\n",
// SearchCity->MinDist[0],SearchCity->CityName);
MiniVal=SearchCity->MinDist[Column];
NextRoute=SearchCity->RoadList;
NextCol=SearchCity->Colum;
while (NextRoute)
{
ULONG dist;
if(Column==0)
{ // We're talking distance
dist=ConvertDist(NextRoute->Distance,NextRoute->Units,
UNITS_METRIC);
}
else
{ // We're talking time
dist=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
NextRoute->Distance,NextRoute->Units,MeasureUnits);
if(dist==0 && debugoutput)
{
Printf("Zero time: %s (%s - %s)\n",NextRoute->Hiway,
NextRoute->CityNum[0]->CityName,
NextRoute->CityNum[1]->CityName);
}
}
OtherCity=NextRoute->CityNum[1-NextCol];
Travel=MiniVal+dist;
if (OtherCity->MinDist[Column] > Travel)
/* found a new shortest path */
{
OtherCity->MinDist[Column]=Travel;
OtherCity->NextCity[Column]=SearchCity;
if(!OtherCity->WorkList && ELink!=OtherCity)
{
BLink=SearchCity;
FLink=SearchCity->WorkList;
while(FLink && Travel>FLink->MinDist[Column])
{
BLink=FLink;
FLink=BLink->WorkList;
}
BLink->WorkList=OtherCity;
OtherCity->WorkList=FLink;
if (!FLink) ELink=OtherCity;
} /* build new Worklist */
} /* shorter total distance */
if(Travel < ThisDist[Column]) ThisDist[Column]=Travel;
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
} /* Try another route from SearchCity */
} /* City within target range */
} /* Next Column */
BLink=SearchCity->WorkList;
SearchCity->WorkList=NULL;
SearchCity=BLink;
} /* if SearchCity not zero, go back */
for(Column=0; Column<2; Column++)
{
SearchCity=Start;
FLink=SearchCity->NextCity[Column];
while(FLink)
{
if(TrailPoint[Column]<MAXTRAIL)
Trail[TrailPoint[Column]++][Column].ct_City=FLink;
SearchCity=FLink;
FLink=SearchCity->NextCity[Column];
} /* wend for next FLink */
} /* next Column */
}
void PrintRoute(char *filename, struct CityData **point, UWORD points,
BOOL isprinter)
{
unsigned char Column, NextCol, NewCol, ColStart, ColEnd;
unsigned short TrackTrail,Result[3][2],i;
unsigned long mpg,truedist,truetime;
struct CityData *FLink, *SearchCity;
struct RouteData *NextRoute, *NewRoute;
struct TripEntry te;
BPTR file;
static char tempstr[100];
file=Open(filename,MODE_NEWFILE);
if(!file)
{
if(isprinter)
MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't write to printer");
else
MUI_Request(app,NULL,0,NULL,"_Ok","Couldn't open output file\n%s",
filename);
return;
}
for(Column=0; Column<2; Column++)
{
Result[0][Column]=0; /* dist */
Result[1][Column]=0; /* time */
Result[2][Column]=0; // fuel
SearchCity=point[0];
for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
{
FLink=Trail[TrackTrail][Column].ct_City;
NextRoute=SearchCity->RoadList;
NextCol=SearchCity->Colum;
while (NextRoute && FLink != NextRoute->CityNum[1-NextCol])
{
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
}
if(NextRoute->SpeedCode>=INTERSTATE_RURAL)
mpg=MPG[NextRoute->SpeedCode-2];
else
mpg=DefaultMPG;
truedist=ConvertDist(NextRoute->Distance,NextRoute->Units,MeasureUnits);
truetime=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
NextRoute->Distance,NextRoute->Units,MeasureUnits);
Result[2][Column]=Result[2][Column]+((100*truedist/mpg)+50)/100;
Result[1][Column]=Result[1][Column]+truetime;
Result[0][Column]=Result[0][Column]+truedist;
SearchCity=FLink;
} /* next Link */
} /* next Column */
ColStart=0;
ColEnd=1;
if(Result[0][0]==Result[0][1])
{
ColStart=1;
ColEnd=1;
}
if(Result[1][0]==Result[1][1])
{
ColStart=0;
ColEnd=0;
}
for(Column=ColStart; Column<=ColEnd; Column++)
{
UWORD dist=0, time=0, cumdist=0, cumtime=0;
FPrintf(file,"From:\t%s, %s\nTo:\t%s, %s\n",point[0]->CityName,
point[0]->StateName,point[points-1]->CityName,
point[points-1]->StateName);
if(points>2)
{
FPrintf(file,"Via:\t");
for(i=1;i<(points-1);i++)
{
FPrintf(file,"%s, %s\n",point[i]->CityName,point[i]->StateName);
if(i<(points-2)) FPrintf(file,"\t");
else FPrintf(file,"\n");
}
}
switch(Column)
{
case 0: FPrintf(file,"Shortest route\n");
break;
case 1: FPrintf(file,"Quickest route\n");
break;
case 2: FPrintf(file,"Preferred route\n");
break;
}
SearchCity=point[0];
for(TrackTrail=0; TrackTrail<TrailPoint[Column]; TrackTrail++)
{
FLink=Trail[TrackTrail][Column].ct_City;
NextRoute=SearchCity->RoadList;
NextCol=SearchCity->Colum;
while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol])
{
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
} /* wend, no NextRoute */
/* Print highway link information */
te.te_Distance=ConvertDist(NextRoute->Distance,NextRoute->Units,
MeasureUnits);
te.te_Time=ConvertToTime(NextRoute->SpeedCode,NextRoute->Speed,
NextRoute->Distance,NextRoute->Units,MeasureUnits);
te.te_Route=NextRoute->Hiway;
if(Stricmp(NextRoute->Exits[1-NextCol],""))
{
SPrintf(tempstr,"%s (Exit %s)",FLink->CityName,
NextRoute->Exits[1-NextCol]);
te.te_End=tempstr;
}
else te.te_End=FLink->CityName;
dist+=te.te_Distance;
time+=te.te_Time;
cumdist+=te.te_Distance;
cumtime+=te.te_Time;
if(Stricmp(SearchCity->StateName,FLink->StateName))
{
FPrintf(file,"CROSSING FROM %s TO %s\n",SearchCity->StateName,
FLink->StateName);
}
if(TrackTrail+1<TrailPoint[Column] && DisplayType &&
!Trail[TrackTrail][Column].ct_Waypoint)
{
NextRoute=FLink->RoadList;
NextCol=FLink->Colum;
FLink=Trail[TrackTrail+1][Column].ct_City;
while (NextRoute && FLink!=NextRoute->CityNum[1-NextCol])
{
NewRoute=NextRoute->RLink[NextCol];
NewCol=NextRoute->Colm[NextCol];
NextRoute=NewRoute;
NextCol=NewCol;
} /* wend, no NextRoute */
FLink=Trail[TrackTrail][Column].ct_City;
if(DisplayType==DIS_ROUTECHANGE)
{
if(!Stricmp(NextRoute->Hiway,te.te_Route))
{
SearchCity=FLink;
continue;
}
}
if(DisplayType==DIS_STATECHANGE)
{
if(!Stricmp(FLink->StateName,SearchCity->StateName) &&
!Stricmp(NextRoute->Hiway,te.te_Route))
{
SearchCity=FLink;
continue;
}
}
}
FPrintf(file,"%4ld %s (%2ld:%02ld) [%4ld %s (%2ld:%02ld)] %s to %s\n",
dist,distabbrevs[MeasureUnits],time/60,time%60,
cumdist,distabbrevs[MeasureUnits],cumtime/60,cumtime%60,
te.te_Route,te.te_End);
if(Trail[TrackTrail][Column].ct_Waypoint)
{
FPrintf(file,"ARRIVED %s, %s: %ld %s%s - %ld:%02ld\n",
FLink->CityName,FLink->StateName,
cumdist,distnames[MeasureUnits],(cumdist==1 ? "" : "s"),
cumtime/60,cumtime%60);
cumdist=0;
cumtime=0;
}
dist=0;
time=0;
SearchCity=FLink;
} /* next link */
FPrintf(file,"\n");
FPrintf(file," Total Distance: %ld %s%s\n",Result[0][Column],
distnames[MeasureUnits],(Result[0][Column]==1 ? "" : "s"));
FPrintf(file," Driving Time: %ld:%02ld\n",Result[1][Column]/60,
Result[1][Column]%60);
FPrintf(file," Fuel used: %ld %s%s\n",Result[2][Column],
fuelunits[MeasureUnits],(Result[2][Column]==1 ? "" : "s"));
if(isprinter) FPrintf(file,"\f");
else FPrintf(file,"\n\n");
} /* next Column */
Close(file);
}